﻿using System.IO;
using AutoMapper;
using H2.NET.Common;
using H2.NET.Data.Common;
using H2.NET.Web.Pages.SMD.Helper;
using H2.NET.Web.Pages.SMD.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;

namespace H2.NET.Web.Pages.SMD.Service
{
    public static class ChangeLogService
    {
        /// <summary>
        /// 获取最新更新的变更日志
        /// </summary>
        /// <param name="assIds"></param>
        /// <returns></returns>
        public static List<t_StoreDataChangeLog> GetLastChangeLogs(List<string> assIds)
        {
            IList<t_StoreDataChangeLog> changeLogs = new List<t_StoreDataChangeLog>();
            if (assIds != null && assIds.Count > 0)
            {
                changeLogs = (t_StoreDataChangeLog._AssessmentID.In(assIds)).List<t_StoreDataChangeLog>(null, " logid desc ");
            }

            return changeLogs.Distinct(new StoreDataChangeLogComparer()).ToList();
        }
        public static List<t_StoreDataChangeLog> GetLastChangeLogs(TaskAPI TaskAPI)
        {
            var assIds = AssessmentService.GetIdsByTaskApi(TaskAPI);

            IList<t_StoreDataChangeLog> changeLogs = new List<t_StoreDataChangeLog>();
            if (assIds != null && assIds.Count > 0)
            {
                changeLogs = (t_StoreDataChangeLog._AssessmentID.In(assIds)).List<t_StoreDataChangeLog>(null, " logid desc ");
            }

            return changeLogs.Distinct(new StoreDataChangeLogComparer()).ToList();
        }

        public static List<t_smd_StoreDataChangeLog> GetLastSmdChangeLogs(TaskAPI taskApi)
        {
            var assIds = AssessmentService.GetIdsByTaskApi(taskApi);

            IList<t_smd_StoreDataChangeLog> changeLogs = new List<t_smd_StoreDataChangeLog>();
            if (assIds != null && assIds.Count > 0)
            {
                changeLogs = (t_smd_StoreDataChangeLog._AssessmentID.In(assIds)).List<t_smd_StoreDataChangeLog>(Storage.Context3);
            }

            return changeLogs.ToList();
        }

        public static List<t_StoreDataChangeLog> GetChangeLogs(List<string> assIds)
        {
            IList<t_StoreDataChangeLog> changeLogs = new List<t_StoreDataChangeLog>();
            if (assIds != null && assIds.Count > 0)
            {
                changeLogs = (t_StoreDataChangeLog._AssessmentID.In(assIds)).List<t_StoreDataChangeLog>(null, " logid desc ");
            }

            return changeLogs.ToList();
        }
        public static List<t_StoreDataChangeLog> FormatChangeLogs(List<t_StoreDataChangeLog> changeLogs)
        {
            foreach (var log in changeLogs)
            {
                string key = GetTableName(log.Category) + "." + log.FieldName;
                log.FieldName = HttpContext.Current.Cache.Get(key.Trim()) == null ? key : HttpContext.Current.Cache.Get(key.Trim()).ToString();

                if (log.FieldName.Trim() == "t_smd_Store.ShortName") { log.FieldName = "经销商简称"; }
                if (!string.IsNullOrEmpty(log.BeforeValue))
                {
                    log.BeforeValue = ConvertValue(log.BeforeValue);
                }
                if (!string.IsNullOrEmpty(log.AfterValue))
                {
                    log.AfterValue = ConvertValue(log.AfterValue);
                }

                // 外键字段转中文
                var foreignKey= new List<string>
                {
                    "t_smd_Store.DealerID",
                    "t_smd_Device.StoreID"
                };

                if (foreignKey.Contains(key))
                {
                    var beforeValue = Utils.StrToInt(log.BeforeValue, 0);
                    log.BeforeValue = beforeValue > 0 ? DealerService.GetById(beforeValue).Name : "无";

                    var afterValue = Utils.StrToInt(log.AfterValue, 0);
                    log.AfterValue = afterValue > 0 ? DealerService.GetById(afterValue).Name : "无";
                }

                // 日期类型特殊处理
                var dateTimeKey = new List<string>
                {
                    //"t_smd_Store.FirstStartDate",
                    //"t_smd_Store.CurrentStartDate",
                    //"t_smd_Store.LastRenewDate"
                };
                if (dateTimeKey.Contains(key))
                {
                    if (!string.IsNullOrEmpty(log.BeforeValue))
                    {
                        log.BeforeValue = Utils.StrToDateTime(log.BeforeValue).ToString("yyyy-MM");
                    }

                    if (!string.IsNullOrEmpty(log.AfterValue))
                    {
                        log.AfterValue = Utils.StrToDateTime(log.AfterValue).ToString("yyyy-MM");
                    }
                }
            }

            return changeLogs;
        }
        public static string GetChangeLogsContent(TaskAPI taskapi)
        {
            var assIds = AssessmentService.GetIdsByTaskApi(taskapi);
            var changeLogs = FormatChangeLogs(GetLastChangeLogs(assIds));

            var resultBuilder = new StringBuilder();

            foreach (var log in changeLogs)
            {
                var beforeValue = string.IsNullOrEmpty(log.BeforeValue) ? "NA" : log.BeforeValue;
                var afterValue = string.IsNullOrEmpty(log.AfterValue) ? "NA" : log.AfterValue;

                var str = string.Format("{0} 变更前：{1} 变更后：{2} 提交人：{3}",
                    log.FieldName, beforeValue, afterValue, log.UserID);
                resultBuilder.AppendLine(str);
                resultBuilder.Append(Environment.NewLine);
            }

            return resultBuilder.ToString();
        }

        public static string GenerateExcel(TaskAPI taskapi)
        {
            // 获取数据
            var assIds = AssessmentService.GetIdsByTaskApi(taskapi);
            var changeLogs = FormatChangeLogs(GetLastChangeLogs(assIds));

            if (changeLogs == null || !changeLogs.Any()) return "";

            var applicationNo = Workflow.Helper.TaskHelper.GetVariableBySingleValue(taskapi, "ApplicationNo");

            // 保存路径
            var folderPath = "~/Pages/SMD/Excel/" + taskapi.Process + "/";
            if (!Directory.Exists(HttpContext.Current.Server.MapPath(folderPath)))
            {
                Directory.CreateDirectory(HttpContext.Current.Server.MapPath(folderPath));
            }
            
            // 保存的文件路径
            var filepath = folderPath + applicationNo + ".xls";
            IWorkbook workbook = new HSSFWorkbook();
            if (File.Exists(HttpContext.Current.Server.MapPath(filepath)))
            {
                workbook = new HSSFWorkbook(new FileStream(HttpContext.Current.Server.MapPath(filepath), FileMode.Open));
            }

            // 如果该步骤已经存在了，就删除该sheet
            int sheetIndex = workbook.GetSheetIndex(taskapi.Step);
            if (sheetIndex > -1)
            {
                workbook.RemoveSheetAt(sheetIndex);
            }

            // 创建sheet
            ISheet sheet = workbook.CreateSheet(taskapi.Step);

            // 创建第一行头部标题
            var isDevice = false;
            IRow headerRow = sheet.CreateRow(0);
            var headlist = new List<string>();
            headlist.Add("门店授权号");
            headlist.Add("门店名称");
            if (changeLogs.FirstOrDefault().Category.Contains("Device"))
            {
                headerRow.CreateCell(2).SetCellValue("设备固定资产号");
            }
            headlist.Add("变更字段");
            headlist.Add("变更前");
            headlist.Add("变更后");
            headlist.Add("提交人");
            for (int i = 0; i < headlist.Count; i++)
            {
                isDevice = true;
                headerRow.CreateCell(i).SetCellValue(headlist[i]);
            }

            // 创建内容
            for (var i = 0; i < changeLogs.Count; i++)
            {
                IRow dataRow = sheet.CreateRow(i + 1);

                var changelog = changeLogs[i];
                var beforeValue = string.IsNullOrEmpty(changeLogs[i].BeforeValue) ? "" : changelog.BeforeValue;
                var afterValue = string.IsNullOrEmpty(changeLogs[i].AfterValue) ? "" : changelog.AfterValue;

                if (changelog.Category.Contains("Device") && !changelog.Category.Contains("Contract"))
                {
                    var device = DeviceService.GetSmdDeviceById(Utils.StrToInt(changelog.DataID, 0));
                    if (device == null || device.DeviceID == 0) continue;
                    var store = StoreService.GetSmdStoreById(device.StoreID.Value);
                    if (store == null || store.StoreID == 0) continue;
                    dataRow.CreateCell(0).SetCellValue(store.AuthID);
                    dataRow.CreateCell(1).SetCellValue(store.StoreName);
                    dataRow.CreateCell(2).SetCellValue(device.FullSetSN);
                    dataRow.CreateCell(3).SetCellValue(changelog.FieldName);
                    dataRow.CreateCell(4).SetCellValue(beforeValue);
                    dataRow.CreateCell(5).SetCellValue(afterValue);
                    dataRow.CreateCell(6).SetCellValue(changelog.UserID);
                }
                else if (changelog.Category == "BatchChangeContract" || changelog.Category == "ChangeStoreContract")
                {
                    var contract = ContractService.GetContractByID(Utils.StrToInt(changelog.DataID, 0));
                    if (contract == null || contract.ContractID == 0) continue;
                    var store = StoreService.GetSmdStoreById(contract.StoreID.Value);
                    if (store == null || store.StoreID == 0) continue;
                    dataRow.CreateCell(0).SetCellValue(store.AuthID);
                    dataRow.CreateCell(1).SetCellValue(store.StoreName);
                    dataRow.CreateCell(2).SetCellValue(changelog.FieldName);
                    dataRow.CreateCell(3).SetCellValue(beforeValue);
                    dataRow.CreateCell(4).SetCellValue(afterValue);
                    dataRow.CreateCell(5).SetCellValue(changelog.UserID);
                }
                else if (changelog.Category == "BatchChangeContractDevice" || changelog.Category == "ChangeDeviceContract")
                {
                    var contractDevice = ContractService.GetContractDeviceByID(Utils.StrToInt(changelog.DataID, 0));
                    if (contractDevice == null || contractDevice.ContractDeviceID == 0) continue;
                    var contract = ContractService.GetContractByStoreID(contractDevice.StoreID);
                    if (contract == null || contract.ContractID == 0) continue;
                    var store = StoreService.GetSmdStoreById(contract.StoreID.Value);
                    if (store == null || store.StoreID == 0) continue;
                    dataRow.CreateCell(0).SetCellValue(store.AuthID);
                    dataRow.CreateCell(1).SetCellValue(store.StoreName);
                    dataRow.CreateCell(2).SetCellValue(changelog.FieldName);
                    dataRow.CreateCell(3).SetCellValue(beforeValue);
                    dataRow.CreateCell(4).SetCellValue(afterValue);
                    dataRow.CreateCell(5).SetCellValue(changelog.UserID);
                }
                else
                {
                    var store = StoreService.GetSmdStoreById(Utils.StrToInt(changelog.DataID, 0));
                    if (store == null || store.StoreID == 0) continue;
                    dataRow.CreateCell(0).SetCellValue(store.AuthID);
                    dataRow.CreateCell(1).SetCellValue(store.StoreName);
                    dataRow.CreateCell(2).SetCellValue(changelog.FieldName);
                    dataRow.CreateCell(3).SetCellValue(beforeValue);
                    dataRow.CreateCell(4).SetCellValue(afterValue);
                    dataRow.CreateCell(5).SetCellValue(changelog.UserID);
                }
            }

            sheet.AutoSizeColumns();

            // 写入内存
            var ms = new MemoryStream();
            workbook.Write(ms);
            ms.Flush();
            ms.Position = 0;

            // 保存至服务器
            var serverPath = HttpContext.Current.Server.MapPath(filepath);
            using (var fs = new FileStream(serverPath, FileMode.Create, FileAccess.Write))
            {
                var data = ms.ToArray();

                fs.Write(data, 0, data.Length);
                fs.Flush();
            }

            return File.Exists(serverPath) ? serverPath : "";
        }
        /// <summary>
        /// 自动设置Excel列宽
        /// </summary>
        /// <param name="sheet">Excel表</param>
        private static void AutoSizeColumns(this ISheet sheet)
        {
            if (sheet.PhysicalNumberOfRows > 0)
            {
                IRow headerRow = sheet.GetRow(0);

                for (int i = 0, l = headerRow.LastCellNum; i < l; i++)
                {
                    sheet.AutoSizeColumn(i);
                }
            }
        }

        /// <summary>
        /// 排除未修改的数据
        /// </summary>
        /// <param name="new_logs"></param>
        /// <param name="existing_logs"></param>
        /// <returns></returns>
        public static List<t_StoreDataChangeLog> GetDistinctChangeLogs(List<t_StoreDataChangeLog> new_logs, List<t_StoreDataChangeLog> existing_logs)
        {
            var logs = new List<t_StoreDataChangeLog>();
            foreach (var log in new_logs)
            {
                var flag = true;
                foreach (var existing_changelog in existing_logs)
                {
                    if (log.FieldName == existing_changelog.FieldName &&
                        log.DataID == existing_changelog.DataID &&
                        log.BeforeValue == existing_changelog.BeforeValue &&
                        log.AfterValue == existing_changelog.AfterValue)
                    {
                        flag = false;
                        continue;
                    }
                }
                if (flag) logs.Add(log);
            }
            return logs;
        }
        /// <summary>
        /// mcd转到smd
        /// </summary>
        /// <param name="assIds"></param>
        /// <returns></returns>
        public static List<t_smd_StoreDataChangeLog> McdToSmd(List<string> assIds)
        {
            Mapper.CreateMap<t_StoreDataChangeLog, t_smd_StoreDataChangeLog>();

            var mdc_changelogs = GetLastChangeLogs(assIds);

            List<t_smd_StoreDataChangeLog> smd_changelogs = Mapper.Map<IList<t_StoreDataChangeLog>, List<t_smd_StoreDataChangeLog>>(mdc_changelogs);

            foreach (t_smd_StoreDataChangeLog smd_changelog in smd_changelogs)
            {
                smd_changelog.EntityState._FieldState.Remove("LogID");
            }

            return smd_changelogs;
        }

        public static List<t_smd_StoreDataChangeLog> McdToSmd(List<t_StoreDataChangeLog> logs)
        {
            Mapper.CreateMap<t_StoreDataChangeLog, t_smd_StoreDataChangeLog>();

            var mdc_changelogs = logs;

            List<t_smd_StoreDataChangeLog> smd_changelogs = Mapper.Map<IList<t_StoreDataChangeLog>, List<t_smd_StoreDataChangeLog>>(mdc_changelogs);

            foreach (t_smd_StoreDataChangeLog smd_changelog in smd_changelogs)
            {
                smd_changelog.EntityState._FieldState.Remove("LogID");
            }

            return smd_changelogs;
        }

        private static string ConvertValue(string value)
        {
            if (value == "True") return "是";
            if (value == "False") return "否";

            if (value.Length > 7)
            {
                DateTime dt;
                if (DateTime.TryParse(value, out dt))
                {
                    return dt.ToString("yyyy-MM-dd");
                }
            }

            return value;
        }

        private static string GetTableName(string category)
        {
            switch (category)
            {
                case "ChangeDevice":
                    return "t_smd_Device";
                case "ChangeStore":
                    return "t_smd_Store";
                case "ChangeStoreContract":
                    return "t_smd_Contract";
                case "DegradeStore":
                    return "t_smd_Store";
                case "ChangeDealer":
                    return "t_smd_Store";
                case "ChangeDeviceContract":
                    return "t_smd_ContractDevice";

                case "BatchDevice":
                    return "t_smd_Device";
                case "BatchStore":
                    return "t_smd_Store";
                case "BatchContract":
                    return "t_smd_Contract";

                default:
                    return "";
            }
        }

        private static string ConvertDealer(int value)
        {
            if (value > 0)
            {
                return DealerService.GetById(value).Name;
            }
            else
            {
                return "无";
            }
        }


        public static void DeleteLogs(List<int> logIds)
        {
            if (logIds != null && logIds.Count > 0)
            {
                (t_StoreDataChangeLog._LogID.In(logIds)).Delete<t_StoreDataChangeLog>();
            }
        }
    }
}